home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS16.ADF / C / FileZap3 / FileZap.c < prev    next >
C/C++ Source or Header  |  1989-01-27  |  12KB  |  414 lines

  1. /* FileZAP.c : (c) 1986 John Hodgson
  2.    
  3.    FileZAP provides a disk-based file zap utility as popularized
  4.    on TRS systems. Although tested, the author cannot be held liable
  5.    for incidental or consequential damage incurred through the use
  6.    of this program.
  7.  
  8.    Special attention was paid to correct and proper EOF handling;
  9.    please notify the author of any discrepancies (cursor movement
  10.    errors, file growth and/or shrinkage)
  11.  
  12.    Note : Although the physical length of Amiga sectors is just short
  13.    of 512 bytes, 256 byte records are the longest ones that can be
  14.    displayed nicely on a 80x24 screen with all pertinent information.
  15.  
  16.    Have fun! Let's help make this world free from protected disks!
  17.  
  18.    John Hodgson
  19.    P.O. Box 1643
  20.    Pebble Beach, Ca. 93953
  21. */
  22.  
  23. /* Revision History
  24.  
  25.    Rev 3.0 : Added new console I/O, causing smaller code, faster
  26.          speed, and a much cleaner (UNIX style) program.  jec
  27.  
  28.    Rev 2.4 : A few extra changes.  jec
  29.  
  30.    Rev 2.3 : Screen cursor changed for better legibility, also
  31.          several routines optimized for speed.  jec
  32.  
  33.    Rev 2.2 : Certain portability problems resolved for Aztec "C"
  34. */
  35.  
  36. #include "fcntl.h"
  37. #include "exec/types.h"
  38. #include "intuition/intuition.h"
  39.  
  40. #define getchar mygetc
  41. #define putchar myputc
  42. #define puts    myputs
  43. #define printf  myprintf
  44. #define exit    myexit
  45.  
  46. #define CR 13
  47. #define EOF 0
  48. #define ERROR -1
  49. #define HEX 0
  50. #define ASC 1
  51.  
  52. char WindowTitle[] = "FileZap Ver 3.0 by John Hodgson & Jim Cooper";
  53.  
  54. /* record buffer physical cursor position (0-15 rows x 0-15 cols) */
  55. int phycurx=0,phycury=0;
  56.  
  57. /* physical x-position to video x-cursor map table */
  58. int posconv[16]={ 6,8,10,12,15,17,19,21,24,26,28,30,33,35,37,39 };
  59.  
  60. void error(str, arg)
  61. char *str, *arg;
  62. {
  63.   int len;
  64.   char strbuf[80];
  65.  
  66.   len = sprintf(&strbuf[0],str,arg);
  67.   prstr((80-len)/2+1,10,strbuf);
  68.   prstr(25,12,"(Press any key to exit)\n");
  69.   len = getchar();
  70. }
  71.  
  72. main(argc,argv)
  73. int argc;
  74. char *argv[];
  75. {
  76.   unsigned char inkey,prevchar,secbuf[256];
  77.   int rdfp,status,lastrec,curec,shiftnum,eof,col;
  78.   long lseek();
  79.  
  80.   if (argc!=2) {
  81.     error("\x9B33mUsage :\x9B31m %s <filename>\n", argv[0]);
  82.     exit(0x55);
  83.   }
  84.  
  85.   if ((rdfp=open(argv[1],O_RDWR))==ERROR) {
  86.     error("\x9B33mError opening file\x9B31m %s\n",argv[1]);
  87.     exit(0x4F);
  88.   }
  89.  
  90.   curec=1; shiftnum=0;
  91.   lastrec=(lseek(rdfp,-1L,2)/256)+1; /* compute last record #, 1..n */
  92.  
  93.   /* compute EOF remainder by reading from last record */ 
  94.   lseek(rdfp,(long)((lastrec-1)*256),0); eof=read(rdfp,&secbuf[0],256);
  95.  
  96.   /* All data gathered, read 1st record */
  97.   lseek(rdfp,0L,0); status=read(rdfp,&secbuf[0],256);
  98.  
  99.   for (col=0;col<=0xf0;col+=0x10)
  100.     printf("%02X : \n", col);
  101.   
  102.   prstr(62,1,"Cur rec :");
  103.   prstr(62,2,"End rec :");
  104.   prstr(62,3,"Offset  :");
  105.   locate(62,5);
  106.   printf("EOF : %d",eof+((lastrec-1)*256)-1);
  107.   prstr(62,9,"Loc : ");
  108.  
  109.   prstr(8,18,"COMMANDS : S) Starting record      E) Ending record");
  110.   prstr(8,19,"           F) Forward record       B) Backward record");
  111.   prstr(8,20,"           U) Update record        R) Recover record");
  112.   prstr(8,21,"      <SPACE> Enter HEX modify     *) Enter ASCII modify");
  113.   prstr(8,22,"        <n>CR Goto record n        ^C Exit program");
  114.  
  115.   locate(1,23);
  116.   printf("File : %s", argv[1]);
  117.  
  118.   display_record(&secbuf[0],curec,lastrec,status);
  119.   movecur(&secbuf[0],0,0,status); /* display initial cursor */
  120.   show_offset(curec);  /* show offset into file */
  121.   prevchar='\0'; /* zero previous char (used for escape checks) */
  122.  
  123.   do {
  124.     inkey = getchar(); /* synchronous kybd scan */
  125.  
  126.     if (prevchar==0x9b) { /* Give 2-byte CSI sequences priority (arrows) */
  127.       prevchar='\0';
  128.       switch(inkey) {
  129.         case 'A':
  130.           movecur(&secbuf[0],0,-1,status);
  131.       show_offset(curec);
  132.           break;
  133.         case 'B':
  134.           movecur(&secbuf[0],0,1,status);
  135.       show_offset(curec);
  136.           break;
  137.         case 'C':
  138.           movecur(&secbuf[0],1,0,status);
  139.       show_offset(curec);
  140.           break;
  141.         case 'D':
  142.           movecur(&secbuf[0],-1,0,status);
  143.       show_offset(curec);
  144.           break;
  145.       }
  146.       continue; /* no point in further tests, restart */
  147.     }
  148.  
  149.     inkey=toupper(inkey); /* force UC for testing */
  150.        
  151.     /* "Goto" record handling - buffer all digits into a shift
  152.        register until too large, or non-digit pressed */
  153.  
  154.     if (isdigit(inkey)) shiftnum=shiftnum*10+inkey-'0';
  155.     else
  156.       if (inkey!=CR) shiftnum=0;
  157.     if (shiftnum>lastrec) shiftnum=0;
  158.  
  159.     if ((inkey==13) && (shiftnum>0)) { /* Goto */
  160.       lseek(rdfp,(long)(256*(shiftnum-1)),0);
  161.       status=read(rdfp,&secbuf[0],256);
  162.       curec=shiftnum; shiftnum=0;
  163.       display_record(&secbuf[0],curec,lastrec,status);
  164.       phycurx=phycury=0; movecur(&secbuf[0],0,0,status);
  165.       show_offset(curec);
  166.     }
  167.     if ((inkey=='F') && (curec<lastrec)) { /* Forward record */
  168.       status=read(rdfp,&secbuf[0],256);
  169.       ++curec;
  170.       display_record(&secbuf[0],curec,lastrec,status);
  171.       phycurx=phycury=0;movecur(&secbuf[0],0,0,status);
  172.       show_offset(curec);
  173.     }
  174.     if ((inkey=='B') && (curec>1)) { /* Backward record */
  175.       --curec;
  176.       lseek(rdfp,(long)((curec-1)*256),0);
  177.       status=read(rdfp,&secbuf[0],256);
  178.       display_record(&secbuf[0],curec,lastrec,status);
  179.       phycurx=phycury=0;movecur(&secbuf[0],0,0,status);
  180.       show_offset(curec);
  181.     }
  182.     switch(inkey) { 
  183.       case 'R': /* Restore (unmodified) record */
  184.         lseek(rdfp,(long)((curec-1)*256),0);
  185.         status=read(rdfp,&secbuf[0],256);
  186.         display_record(&secbuf[0],curec,lastrec,status);
  187.         phycurx=phycury=0;movecur(&secbuf[0],0,0,status);
  188.     show_offset(curec);
  189.         break;
  190.       case 'S': /* Rewind */
  191.         curec=1;
  192.         lseek(rdfp,0L,0);
  193.         status=read(rdfp,&secbuf[0],256);
  194.         display_record(&secbuf[0],curec,lastrec,status);
  195.         phycurx=phycury=0;movecur(&secbuf[0],0,0,eof);
  196.     show_offset(curec);
  197.         break;
  198.       case 'U': /* Update (save modified) record */
  199.         lseek(rdfp,(long)-status,1);
  200.         write(rdfp,&secbuf[0],status);
  201.         DisplayBeep(NULL);
  202.         break;
  203.       case 'E': /* skip to Ending record */
  204.         curec=lastrec;
  205.         lseek(rdfp,(long)(curec-1)*256,0);
  206.         status=read(rdfp,&secbuf[0],256);
  207.         display_record(&secbuf[0],curec,lastrec,status);
  208.         phycurx=phycury=0;movecur(&secbuf[0],0,0,status);
  209.     show_offset(curec);
  210.         break;
  211.       case ' ': /* Enter hex-modify mode */
  212.         edit_window(curec,&secbuf[0],status,HEX);
  213.         break;
  214.       case '*': /* Enter ascii-modify mode */
  215.         edit_window(curec,&secbuf[0],status,ASC);
  216.     break;
  217.     }
  218.     prevchar=inkey; /* update previous char for CSI sequence checks */
  219.   }
  220.   while (inkey!=3); /* loop until CTRL-C */
  221.   
  222.   close(rdfp); exit(0); /* cleanup & exit */
  223. }
  224.  
  225. display_record(secbuf,curec,finsec,eof)
  226. int curec,finsec,eof;
  227. char secbuf[16][16];
  228.  
  229. {
  230.   int row,col,i;
  231.   char strbuf[100],*kludge;
  232.  
  233.   /* kludge maps 2-d array to 1-d so we can more easily
  234.      fill incomplete records w/dummy chars past EOF */
  235.  
  236.   kludge=&secbuf[0][0];
  237.   for (i=256;i>eof;--i) kludge[i-1]='#';
  238.  
  239.   /* EOL's included below to erase old values */
  240.   locate(72,1); printf("\x9bK%d",curec);
  241.   locate(72,2); printf("\x9bK%d",finsec);
  242.  
  243.   /* record display core routine : Due to the slowness of the
  244.      console file drivers, display is line buffered for speed. */
  245.  
  246.   for (row=0;row<=15;row++) {
  247.     i=0;
  248.     for (col=0;col<=15;col++) {
  249.       hexconv(&strbuf[i],secbuf[row][col]); i+=2;
  250.       if (((col+1)%4)==0) strbuf[i++]=' ';
  251.     }
  252.     strbuf[i++]=':'; strbuf[i++]=' ';
  253.     for (col=0;col<=15;col++) strbuf[i++]=valid_display(secbuf[row][col]);
  254.  
  255.     strbuf[i]='\0'; prstr(6,row+1,strbuf);
  256.   }
  257. }
  258.  
  259. locate(x,y) /* move cursor to x,y */
  260. int x,y;
  261. {
  262.   /* complete escape sequence for cursor pos is :
  263.      <CSI><row><;><col><H> where CSI is 9BH. */
  264.  
  265.   printf("\x9b%c%c;%c%cH",(y/10+48),((y%10)+48),(x/10+48),((x%10)+48));
  266. }
  267.       
  268. hexconv(result,byte) /* byte to 2 ASCII hex digits */
  269. unsigned char result[2],byte;
  270. {
  271.   result[0]=(byte>>4)+48+7*((byte>>4)>9);
  272.   result[1]=(byte & 0xf)+48+7*((byte & 0xf)>9);
  273. }
  274.  
  275. prstr(posx,posy,string) /* "Print-At" routine */
  276. int posx,posy;
  277. char *string;
  278. {
  279.   locate(posx,posy);
  280.   printf("%s", string);
  281. }
  282.  
  283. movecur(secbuf,deltax,deltay,eof) /* move cursor & update display */
  284. int deltax,deltay,eof;
  285. char secbuf[16][16];
  286. {
  287.   /* update ASCII side */
  288.   locate(phycurx+44,phycury+1);
  289.   printf("%c", valid_display(secbuf[phycury][phycurx]));
  290.  
  291.   /* disallow cursor movement past EOF */
  292.   
  293.   if (fixpos(eof,deltax,deltay,secbuf)) return(0);
  294.  
  295.   locate(68,9);
  296.   printf("%02X", phycury*16+phycurx); /* update LOC value */
  297.  
  298.   locate(phycurx+44,phycury+1);
  299.   printf("\x9b33m%c\x9b31m", valid_display(secbuf[phycury][phycurx]));
  300.  
  301.   locate(posconv[phycurx],phycury+1); /* update HEX ("real") cursor */
  302. }
  303.  
  304. show_offset(curec)
  305. int curec;
  306. {
  307.   locate(72,3);
  308.   printf("\x9bK%d", ((curec-1)*256)+(phycury*16)+phycurx);
  309.   locate(posconv[phycurx],phycury+1); /* update HEX ("real") cursor */
  310. }
  311.  
  312. edit_window(curec,secbuf,eof,hex) /* record edit routine */
  313. int curec,eof,hex;
  314. char secbuf[16][16];
  315. {
  316.   char ascii,lsb,msb;
  317.   int status=NULL,tempx;
  318.  
  319.   if (hex==HEX) prstr(62,11,"\x9bKModify : HEX");
  320.   else prstr(62,11,"\x9bKModify : ASCII");
  321.  
  322.   prstr(62,12,"<ESC> to exit");
  323.  
  324.   do {
  325.     
  326.     locate(posconv[phycurx],phycury+1); /* cursor over hex digits */
  327.     printf("\x9b33m%02X\x9b31m", secbuf[phycury][phycurx]&255);
  328.     locate(posconv[phycurx],phycury+1); /* restore cursor */
  329.  
  330.     if (hex==HEX) { /* hex-modify : Actually, any invalid char exits */
  331.  
  332.       if ((msb=hexfetch())==FALSE) { status=1; goto exit; }
  333.       putchar(msb); /* print msb */
  334.  
  335.       if ((lsb=hexfetch())==FALSE) { status=1; goto exit; }
  336.       putchar(lsb); /* print lsb */
  337.  
  338.       if (msb>'9') msb-=55; else msb-='0'; /* hex to binary */
  339.       if (lsb>'9') lsb-=55; else lsb-='0';
  340.       secbuf[phycury][phycurx]=(msb<<4)+lsb; /* update buffer */
  341.     }
  342.     else { /* ASCII-modify */
  343.  
  344.       ascii = getchar(); /* fetch ASCII char from user */
  345.       if (ascii==0x1b) { status=1; goto exit; }/* exit on <ESC> */
  346.       secbuf[phycury][phycurx]=ascii; /* update buffer */
  347.     }
  348. exit:
  349.     locate(posconv[phycurx],phycury+1); /* restore cursor */
  350.     printf("%02X", secbuf[phycury][phycurx]&255);
  351.  
  352.     movecur(&secbuf[0],0,0,eof); /* update ASCII side */
  353.     show_offset(curec);
  354.     if (status==1) break; /* don't move cursor if <ESC> */
  355.  
  356.     tempx=phycurx; /* save previous x-coord */
  357.     movecur(&secbuf[0],1,0,eof); /* move to next digit */
  358.     show_offset(curec);
  359.     if (tempx==phycurx) status=1; /* cancel modify if blocked */
  360.   }
  361.   while (status==NULL); /* edit until exit */
  362.  
  363.   prstr(62,11,"\x9bK"); /* erase info msgs */
  364.   prstr(62,12,"\x9bK");
  365.   locate(posconv[phycurx],phycury+1); /* restore cursor B4 exit */
  366. }
  367.  
  368. hexfetch() /* Fetch valid ascii HEX sequence from user */
  369. {
  370.    unsigned char nybble;
  371.  
  372.   for (;;) {
  373.     nybble = getchar();
  374.     if (nybble==0x1b) return(FALSE);
  375.     if (!isalnum(nybble)) continue;
  376.     nybble=toupper(nybble);
  377.     if (nybble>'F') continue;
  378.     return (int)nybble;
  379.   }
  380. }
  381.   
  382. fixpos(eof,deltax,deltay,secbuf) /* cursor bounds check routine */
  383. int eof,deltax,deltay;
  384. char secbuf[16][16];
  385. {
  386.   int tempx,tempy;
  387.  
  388.   tempx=phycurx+deltax; tempy=phycury+deltay;
  389.  
  390.   if (tempx>15) { tempy++; tempx=0; } /* cursor screen-wrap code */
  391.   if (tempy>15) tempy=0;
  392.   if (tempx<0)  { tempx=15; tempy--; }
  393.   if (tempy<0)  tempy=15;
  394.   
  395.   if ((((tempy)*16) + (tempx)) > eof-1) { /* cleanup & exit if past EOF */
  396.     locate(phycurx+44,phycury+1); /* update ASCII cursor */
  397.     printf("\x9b33m%c\x9b31m", valid_display(secbuf[phycury][phycurx]));
  398.     locate(posconv[phycurx],phycury+1); /* redraw HEX cursor */
  399.     DisplayBeep(NULL); /* Flash user so he wakes up */
  400.     return(TRUE); /* and exit */
  401.   }
  402.   phycurx=tempx; phycury=tempy; /* Otherwise, update global cursor */
  403.   return(FALSE);
  404. }
  405.  
  406. valid_display(byte) /* return filtered ASCII char */
  407. char byte;
  408.  
  409. /* Filter all CTRL & CSI chars which could mess things up */
  410. {
  411.   if ((byte>31) && (byte!=0x9b)) return(int)byte;
  412.   else return(int)'.';
  413. }
  414.